package com.donger.business.modules.upms.service.Impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.donger.business.entity.UserDto;
import com.donger.business.entity.UserInfo;
import com.donger.business.modules.upms.entity.*;
import com.donger.business.modules.upms.mapper.SysPermissionMapper;
import com.donger.business.modules.upms.mapper.SysRoleMapper;
import com.donger.business.modules.upms.mapper.SysUserMapper;
import com.donger.business.modules.upms.service.ISysDeptService;
import com.donger.business.modules.upms.service.ISysUserRoleService;
import com.donger.business.modules.upms.service.ISysUserService;
import com.donger.business.service.Global;
import com.donger.common.core.constant.CommonConstants;
import com.donger.common.core.exception.BizException;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotBlank;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统用户 服务实现类
 * </p>
 *
 * @author xyx
 * @since 2019-01-12
 */
@RequiredArgsConstructor
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();
    private final SysPermissionMapper sysPermissionMapper;
    private final ISysUserRoleService sysUserRoleService;
    private final SysRoleMapper sysRoleMapper;

    private final ISysDeptService sysDeptService;


    @Override
    public IPage getUserWithRolePage(Page page, Wrapper<SysUser> queryWrapper) {
        return baseMapper.getUserPage(page, queryWrapper);
    }

    /**
     * 获取用户详情
     * 带角色 和 权限
     *
     * @param sysUser
     * @return
     */
    @Override
    public UserInfo findUserInfo(SysUser sysUser) {
        if (sysUser == null) {
            return null;
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setSysUser(sysUser);
        // 获取角色列表ID
        List<Long> roles = sysRoleMapper.listRolesByUserId(sysUser.getUserId())
                .stream()
                .map(SysRole::getRoleId)
                .collect(Collectors.toList());
        userInfo.setRoles(ArrayUtil.toArray(roles, Long.class));

        // 设置权限列表
        Set<String> permissions = new HashSet<>();
        roles.forEach(role -> {
            List<String> permissionsList = sysPermissionMapper.listMenusByRoleId(role).stream()
                    .filter(sysMenu -> StrUtil.isNotBlank(sysMenu.getPerms()))
                    .map(SysPermission::getPerms)
                    .collect(Collectors.toList());
            permissions.addAll(permissionsList);
        });
        userInfo.setPermissions(ArrayUtil.toArray(permissions, String.class));
        return userInfo;
    }

    /**
     * 根据用户ID 查询用户权限
     *
     * @param userId 用户ID
     * @return 用户权限列表
     */
    @Override
    public List<String> findPermissionsByUserId(Long userId) {
        if (CommonConstants.SUPER_ADMIN.equals(userId)) {
            return sysPermissionMapper.selectList(null).stream().map(SysPermission::getPerms).collect(Collectors.toList());
        }
        return baseMapper.findPermissionsByUserId(userId);
    }

    /**
     * @param currentUserId 当前用ID
     * @param password      原密码
     * @param newPassword   新密码
     * @return true 更新成功 false 更新失败
     */
    @Override
    public boolean updatePassword(Long currentUserId, @NotBlank(message = "旧密码不能为空") String password, @NotBlank(message = "新密码不能为空") String newPassword) {
        SysUser userEntity = getById(currentUserId);
        /**
         * 新密码进行加密
         */
        newPassword = ENCODER.encode(newPassword);

        /**
         * 判断原有密码是否相同
         */
        if (!ENCODER.matches(password, userEntity.getPassword())) {
            throw new BizException("旧密码错误");
        }

        userEntity.setPassword(newPassword);
        return this.update(userEntity,
                new LambdaUpdateWrapper<SysUser>().eq(SysUser::getUserId, currentUserId));
    }

    /**
     * 查询当前用户菜单ID
     *
     * @param currentUserId 当前用户
     * @return 用户菜单ID列表
     */
    @Override
    public List<SysPermission> queryMenuByUserId(Long currentUserId) {
        return sysPermissionMapper.queryMenuByUserId(currentUserId);
    }

    /**
     * 保存用户信息
     *
     * @param user 用户信息
     * @return 保存标识
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveUser(UserDto user) {

        String value = Global.getConfig("sys.user.initPassword", "123456");
        user.setPassword(ENCODER.encode(value));
        baseMapper.insert(user);
        List<SysUserRole> userRoleList = Arrays.stream(user.getRoleIdList()).map(roleId -> {
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(user.getUserId());
            userRole.setRoleId(roleId);
            return userRole;
        }).collect(Collectors.toList());
        return sysUserRoleService.saveBatch(userRoleList);
    }


    /**
     * 更新用户信息
     *
     * @param user 用户信息
     * @return 成功表示
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateUserById(UserDto user) {
        this.updateById(user);
        sysUserRoleService.remove(Wrappers.<SysUserRole>update().lambda()
                .eq(SysUserRole::getUserId, user.getUserId()));
        List<SysUserRole> userRoleList = Arrays.stream(user.getRoleIdList()).distinct().map(roleId -> {
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(user.getUserId());
            userRole.setRoleId(roleId);
            return userRole;
        }).collect(Collectors.toList());
        return sysUserRoleService.saveBatch(userRoleList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteUserById(Long userId) {
        sysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        this.removeById(userId);
        return Boolean.TRUE;
    }

    @Override
    public List<SysUser> listAncestorUsers(Long userId) {
        SysUser sysUser = this.getOne(Wrappers.<SysUser>query().lambda()
                .eq(SysUser::getUserId, userId));
        SysDept sysDept = sysDeptService.getById(sysUser.getDeptId());
        if (sysDept == null) {
            return null;
        }
        return this.list(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDeptId, sysDept.getParentId()));
    }


}
